﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YJKCodeBase.Math;
using YJKRevitCode.TransformUtility;

namespace YJKRevitCode.XYZUtility
{
	public static class XYZUtilityMethod
	{
		public static XYZ SetX(this XYZ inputValue, double inputX)
		{
			if (inputValue == null)
			{
				return null;
			}
			return new XYZ(inputX, inputValue.Y, inputValue.Z);
		}

		public static XYZ SetY(this XYZ inputValue, double inputY)
		{
			if (inputValue == null)
			{
				return null;
			}
			return new XYZ(inputValue.X, inputY, inputValue.Z);
		}

		public static XYZ SetZ(this XYZ inputValue, double inputZ)
		{
			if (inputValue == null)
			{
				return null;
			}
			return new XYZ(inputValue.X, inputValue.Y, inputZ);
		}

		public static int PointInPloygon(List<Curve> lstCurves, XYZ pt)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in lstCurves)
			{
				XYZ endPoint = curve.GetEndPoint(0);
				XYZ endPoint2 = curve.GetEndPoint(1);
				list.Add(endPoint);
				list.Add(endPoint2);
			}
			list = list.Distinct<XYZ>().ToList<XYZ>();
			return XYZUtilityMethod.PointInPloygon(list, pt);
		}

		public static int PointInPloygon(List<XYZ> vecPolypt, XYZ pt)
		{
			List<XYZ> range = vecPolypt.GetRange(0, vecPolypt.Count);
			if (range.Count < 3)
			{
				return -1;
			}
			XYZ xyz = range[0];
			XYZ xyz2 = range[range.Count - 1];
			if (xyz != xyz2)
			{
				range.Add(xyz);
			}
			int num = 0;
			List<XYZ> list = new List<XYZ>();
			XYZ xyz3 = new XYZ(0.0, 0.0, 0.0);
			XYZ xyz4 = xyz3 - pt;
			for (int i = 0; i < range.Count; i++)
			{
				XYZ xyz5 = range[i];
				xyz5 += xyz4;
				list.Add(xyz5);
			}
			XYZ xyz6 = pt + xyz4;
			int num2 = MathUtility.Greaterthan_Or_Equal(list[0].X, 0.0) ? (MathUtility.Greaterthan_Or_Equal(list[0].Y, 0.0) ? 0 : 3) : (MathUtility.Greaterthan_Or_Equal(list[0].Y, 0.0) ? 1 : 2);
			for (int i = 1; i < list.Count; i++)
			{
				XYZ xyz7 = list[i - 1];
				XYZ xyz8 = list[i];
				if (MathUtility.IsEqual(xyz6.DistanceTo(xyz7), 0.0, 0.0001))
				{
					return 0;
				}
				XYZ xyz9 = new XYZ(xyz7.X, xyz7.Y, xyz7.Z);
				XYZ xyz10 = new XYZ(xyz8.X, xyz8.Y, xyz8.Z);
				xyz9 = xyz9.Normalize();
				xyz10 = xyz10.Normalize();
				double num3 = xyz10.Y * xyz9.X - xyz10.X * xyz9.Y;
				if (Math.Abs(num3) < 0.0001 && xyz9.X * xyz10.X <= 0.0001 && xyz9.Y * xyz10.Y <= 0.0001)
				{
					return 0;
				}
				int num4 = MathUtility.Greaterthan_Or_Equal(xyz8.X, 0.0) ? (MathUtility.Greaterthan_Or_Equal(xyz8.Y, 0.0) ? 0 : 3) : (MathUtility.Greaterthan_Or_Equal(xyz8.Y, 0.0) ? 1 : 2);
				if (num4 == (num2 + 1) % 4)
				{
					num++;
				}
				else if (num4 == (num2 + 2) % 4)
				{
					if (num3 > 0.0)
					{
						num += 2;
					}
					else
					{
						num -= 2;
					}
				}
				else if (num4 == (num2 + 3) % 4)
				{
					num--;
				}
				num2 = num4;
			}
			if (num == 0)
			{
				return -1;
			}
			if (Math.Abs(num) == 4)
			{
				return 1;
			}
			return 0;
		}

		public static bool Is_Points_Collinear(XYZ pt1, XYZ pt2, XYZ pt3, double tolerance = 1E-09)
		{
			double num = pt2.X - pt1.X;
			double num2 = pt2.Y - pt1.Y;
			double num3 = pt2.Z - pt1.Z;
			double num4 = pt3.X - pt1.X;
			double num5 = pt3.Y - pt1.Y;
			double num6 = pt3.Z - pt1.Z;
			double num7 = num2 * num6 - num5 * num3;
			double num8 = num4 * num3 - num * num6;
			double num9 = num * num5 - num4 * num2;
			return MathUtility.IsEqual(num7 * num7 + num8 * num8 + num9 * num9, 0.0, tolerance);
		}

		public static XYZ TransformPoint(XYZ point, Transform transform)
		{
			return TransformUtilityMethod.TransformPoint(point, transform);
		}

		public static XYZ CalculatMidPoint(XYZ ptStart, XYZ ptEnd)
		{
			XYZ xyz = ptEnd - ptStart;
			return ptStart + xyz / 2.0;
		}

		public static XYZ UnBoundPlanarFaceProject(PlanarFace inputFace, XYZ inputPoint)
		{
			Transform transform = TransformUtilityMethod.CalculateTransformFromPlanarFaceToXoY(inputFace);
			XYZ origin = inputFace.Origin;
			XYZ xyz = TransformUtilityMethod.TransformPoint(origin, transform);
			XYZ inputValue = TransformUtilityMethod.TransformPoint(inputPoint, transform);
			XYZ point = inputValue.SetZ(xyz.Z);
			return TransformUtilityMethod.TransformPoint(point, transform.Inverse);
		}

		public static XYZ Abs(XYZ input)
		{
			if (input == null)
			{
				return null;
			}
			return new XYZ(Math.Abs(input.X), Math.Abs(input.Y), Math.Abs(input.Z));
		}

		public static bool IsEqual(XYZ pt1, XYZ pt2)
		{
			double val = pt1.DistanceTo(pt2);
			return MathUtility.IsEqual(val, 0.0);
		}

		public static bool IsEqual(XYZ pt1, XYZ pt2, double eps)
		{
			double val = pt1.DistanceTo(pt2);
			return MathUtility.Lessthan_Or_Equal(val, eps);
		}

		public static bool IsParallel(XYZ a, XYZ b)
		{
			double num = a.AngleTo(b);
			return 1E-09 > num || MathUtility.IsEqual(num, Math.PI);
		}

		public static bool IsVertical(XYZ a, XYZ b)
		{
			double val = a.AngleTo(b);
			return MathUtility.IsEqual(val, Math.PI*.5);
		}

		public static XYZ CalculateFootPoint(XYZ ptStart, XYZ ptEnd, XYZ point)
		{
			if (MathUtility.IsEqual(ptStart.DistanceTo(ptEnd), 0.0))
			{
				return ptStart;
			}
			double num = Math.Sqrt((ptEnd.X - ptStart.X) * (ptEnd.X - ptStart.X) + (ptEnd.Y - ptStart.Y) * (ptEnd.Y - ptStart.Y) + (ptEnd.Z - ptStart.Z) * (ptEnd.Z - ptStart.Z));
			double num2 = (ptEnd.X - ptStart.X) * (point.X - ptStart.X) + (ptEnd.Y - ptStart.Y) * (point.Y - ptStart.Y) + (ptEnd.Z - ptStart.Z) * (point.Z - ptStart.Z);
			num = num2 / (num * num);
			double num3 = ptStart.X + (ptEnd.X - ptStart.X) * num;
			double num4 = ptStart.Y + (ptEnd.Y - ptStart.Y) * num;
			double num5 = ptStart.Z + (ptEnd.Z - ptStart.Z) * num;
			return new XYZ(num3, num4, num5);
		}

		public static XYZ CalculateFootPoint(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ point)
		{
			double num = ptCenter.DistanceTo(ptStart);
			XYZ xyz = new XYZ(point.X, point.Y, ptCenter.Z);
			XYZ xyz2 = xyz - ptCenter;
			xyz2 = xyz2.Normalize() * num;
			return ptCenter + xyz2;
		}

		public static bool IsPointInArea(List<Curve> area, XYZ pt)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in area)
			{
				list.AddRange(curve.Tessellate());
			}
			return XYZUtilityMethod.PointInPloygon(list, pt) == 1;
		}

		public static bool IsPointInCurve(Curve curve, XYZ point, bool ifUnBound = true)
		{
			Curve curve2 = curve.Clone();
			if (ifUnBound && curve2.IsBound)
			{
				curve2.MakeUnbound();
			}
			return point.IsAlmostEqualTo(curve2.Project(point).XYZPoint);
		}

		public static bool PointToString(XYZ point, out string pointString)
		{
			bool result;
			try
			{
				pointString = point.ToString();
				result = true;
			}
			catch
			{
				pointString = string.Empty;
				result = false;
			}
			return result;
		}

		public static bool StringToPoint(string pointString, out XYZ point)
		{
			bool result;
			try
			{
				pointString = pointString.Substring(1, pointString.Length - 2);
				string[] array = pointString.Split(new char[]
				{
					','
				});
				point = new XYZ(Convert.ToDouble(array[0]), Convert.ToDouble(array[1]), Convert.ToDouble(array[2]));
				result = true;
			}
			catch
			{
				point = null;
				result = false;
			}
			return result;
		}

		public const double _epsPoint = 0.0001;
	}
}
